// src/renderer/workbench/data.js
// 数据导入与字段映射模块 - v3.5 (修复 prompt 报错 / 替换为自定义弹窗)

// 全局状态管理
let currentImportGroups = {};
let activeGroupKey = null;
let activeDataType = null;

function getDataTypeName(type) {
    const map = {
        bank: '银行流水',
        call: '通话记录',
        travel: '出行记录',
        accommodation: '住宿登记',
        property: '不动产登记',
        railway: '铁路售票',
        flight: '飞机售票',
        business: '工商企业'
    };
    return map[type] || type;
}

// 字段定义
function getFieldDefinitions(type) {
    const defs = {
        bank: [
            { key: 'transaction_time', label: '交易时间', required: true, type: 'date' },
            { key: 'transaction_amount', label: '交易金额', required: true, type: 'number' },
            { key: 'account_number', label: '本方账号', required: true },
            { key: 'counterparty_name', label: '对方户名', required: false },
            { key: 'counterparty_account', label: '对方账号', required: false },
            { key: 'debit_credit_flag', label: '借贷标志', required: false },
            { key: 'balance_after', label: '余额', required: false, type: 'number' },
            { key: 'remarks', label: '备注', required: false },
            { key: 'customer_name', label: '客户名称', required: false },
            { key: 'bank_name', label: '开户行', required: false },
            { key: 'transaction_branch_name', label: '交易网点', required: false }
        ],
        call: [
            { key: 'user_number', label: '本机号码', required: true },
            { key: 'opp_user_number', label: '对方号码', required: true },
            { key: 'start_time', label: '通话时间', required: true, type: 'date' },
            { key: 'duration', label: '通话时长', required: true, type: 'number' },
            { key: 'call_type', label: '呼叫类型', required: false },
            { key: 'user_name', label: '机主姓名', required: false },
            { key: 'lac_id', label: '基站LAC', required: false },
            { key: 'cell_id', label: '基站CI', required: false }
        ],
        accommodation: [
            { key: 'guest_name', label: '姓名', required: true },
            { key: 'id_number', label: '身份证号', required: true },
            { key: 'hotel_name', label: '旅店名称', required: true },
            { key: 'check_in_time', label: '入住时间', required: true, type: 'date' },
            { key: 'check_out_time', label: '离店时间', required: false, type: 'date' },
            { key: 'room_number', label: '房间号', required: false },
            { key: 'hotel_address', label: '旅店地址', required: false }
        ],
        property: [
            { key: 'owner_name', label: '权利人', required: true },
            { key: 'property_address', label: '房地坐落', required: true },
            { key: 'certificate_number', label: '证件号码', required: false },
            { key: 'building_area', label: '建筑面积', required: false, type: 'number' },
            { key: 'property_nature', label: '房屋性质', required: false },
            { key: 'registration_authority', label: '登记机构', required: false }
        ],
        railway: [
            { key: 'passenger_name', label: '姓名', required: true },
            { key: 'id_number', label: '身份证号', required: true },
            { key: 'train_number', label: '车次', required: true },
            { key: 'departure_date', label: '乘车日期', required: true, type: 'date' },
            { key: 'departure_station', label: '出发站', required: true },
            { key: 'arrival_station', label: '到达站', required: true },
            { key: 'seat_number', label: '座位号', required: false }
        ],
        flight: [
            { key: 'passenger_chinese_name', label: '旅客姓名', required: true },
            { key: 'id_number', label: '身份证号', required: true },
            { key: 'flight_number', label: '航班号', required: true },
            { key: 'flight_date', label: '航班日期', required: true, type: 'date' },
            { key: 'departure_port', label: '起飞机场', required: true },
            { key: 'arrival_port', label: '降落机场', required: true },
            { key: 'departure_time', label: '起飞时间', required: false, type: 'date' }
        ],
        business: [
            { key: 'enterprise_name', label: '企业名称', required: true },
            { key: 'unified_social_credit_code', label: '统一社会信用代码', required: false },
            { key: 'legal_representative', label: '法人代表', required: false },
            { key: 'registered_capital', label: '注册资本', required: false, type: 'number' },
            { key: 'establishment_date', label: '成立日期', required: false, type: 'date' },
            { key: 'registration_status', label: '状态', required: false },
            { key: 'address', label: '住所', required: false }
        ],
        travel: [
            { key: 'start_time', label: '开始时间', required: true, type: 'date' },
            { key: 'origin', label: '出发地', required: true },
            { key: 'destination', label: '目的地', required: true },
            { key: 'transport_type', label: '交通工具', required: false }
        ]
    };
    return defs[type] || [];
}

function getSystemFieldOptions(type) {
    const defs = getFieldDefinitions(type);
    return defs.map(item => ({
        value: item.key,
        label: item.label + (item.required ? ' *' : '')
    }));
}

window.importData = async function (dataType, caseId) {
    try {
        const filePaths = await window.electronAPI.file.selectImportFile({
            title: `批量导入 - ${getDataTypeName(dataType)}`,
            filters: [{ name: '表格文件', extensions: ['xlsx', 'xls', 'csv'] }]
        });

        if (!filePaths || filePaths.length === 0) return;

        const loadingDiv = document.createElement('div');
        loadingDiv.id = 'batch-loading-overlay';
        loadingDiv.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);z-index:9999;display:flex;justify-content:center;align-items:center;color:white;font-size:1.2rem;';
        loadingDiv.innerHTML = '<div><div style="margin-bottom:10px;">🔍 正在扫描文件结构...</div><div style="font-size:0.9rem;color:#eee;">正在读取表头指纹与预览数据</div></div>';
        document.body.appendChild(loadingDiv);

        const rawSheets = await window.electronAPI.invoke('inspect-files', filePaths);

        const groups = {};

        for (const sheet of rawSheets) {
            if (sheet.error) continue;
            const sig = sheet.signature;
            if (!groups[sig]) {
                groups[sig] = {
                    id: sig,
                    headers: sheet.headers,
                    files: [],
                    mapping: null,
                    templateName: null,
                    validationStatus: 'pending',
                    previewData: []
                };
            }
            groups[sig].files.push({
                path: sheet.filePath,
                fileName: sheet.fileName,
                sheet: sheet.sheetName,
                rows: sheet.rowCount
            });
        }

        for (const sig of Object.keys(groups)) {
            const g = groups[sig];
            if (g.files.length > 0) {
                const firstFile = g.files[0];
                try {
                    const res = await window.electronAPI.file.parse(firstFile.path, dataType, { sheetName: firstFile.sheet });
                    if (res.success) {
                        g.previewData = res.previewData.slice(0, 10);
                    }
                } catch (e) {
                    console.error('获取预览失败', e);
                }
            }
        }

        document.body.removeChild(loadingDiv);

        if (Object.keys(groups).length === 0) {
            alert('未发现有效数据结构');
            return;
        }

        currentImportGroups = groups;
        showBatchMappingWizard(dataType, currentImportGroups);

    } catch (error) {
        const loading = document.getElementById('batch-loading-overlay');
        if (loading) loading.remove();
        console.error(error);
        alert(`扫描出错: ${error.message}`);
    }
};

async function showBatchMappingWizard(dataType, groups) {
    const groupKeys = Object.keys(groups);

    for (const key of groupKeys) {
        const group = groups[key];
        if (window.TemplateManager && typeof window.TemplateManager.tryAutoMapFromTemplate === 'function') {
            const matched = await window.TemplateManager.tryAutoMapFromTemplate(dataType, group.headers);
            if (matched) {
                group.mapping = matched.mappings;
                group.templateName = matched.name;
            }
        } else {
            const simpleMapping = trySimpleAutoMap(dataType, group.headers);
            if (Object.keys(simpleMapping).length > 0) {
                group.mapping = simpleMapping;
                group.templateName = "自动识别";
            }
        }
    }

    const modalId = `batch-modal-${Date.now()}`;
    let groupsHtml = '';

    groupKeys.forEach((key, idx) => {
        const g = groups[key];
        const fileCount = g.files.length;
        const statusColor = g.mapping ? '#52c41a' : '#faad14';
        const statusText = g.mapping ? `已匹配` : '待配置';
        const isSelected = idx === 0 ? 'background:#e6f7ff; border-color:#1890ff;' : 'background:#fff;';

        const filePreview = g.files.slice(0, 3).map(f =>
            `<div style="font-size:12px;color:#666;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">📄 ${f.fileName} [${f.sheet}]</div>`
        ).join('');

        groupsHtml += `
            <div class="batch-group-card" id="group-card-${key}" onclick="window.selectBatchGroup('${key}', '${dataType}')" 
                 style="border:1px solid #eee; padding:12px; margin-bottom:10px; border-radius:6px; cursor:pointer; border-left:4px solid ${statusColor}; ${isSelected} transition:all 0.2s; position:relative;">
                
                <div onclick="window.removeBatchGroup('${key}', event)" title="移除此结构组"
                     style="position:absolute; top:5px; right:5px; width:20px; height:20px; line-height:20px; text-align:center; color:#999; font-size:16px; border-radius:50%; transition:all 0.2s;"
                     onmouseover="this.style.color='#ff4d4f';this.style.background='#fff1f0'"
                     onmouseout="this.style.color='#999';this.style.background='transparent'">
                     ×
                </div>

                <div style="display:flex; justify-content:space-between; margin-bottom:5px; padding-right:20px;">
                    <strong>结构类型 ${idx + 1}</strong>
                    <span id="status-badge-${key}" style="font-size:12px; color:${statusColor}; font-weight:bold;">${statusText}</span>
                </div>
                <div style="margin-bottom:8px; font-size:0.85rem; color:#666;">包含 ${fileCount} 个工作表</div>
                <div style="background:#f9f9f9; padding:6px; border-radius:4px; border:1px solid #f0f0f0;">${filePreview}</div>
                <div id="validate-icon-${key}" style="text-align:right; margin-top:5px; display:none;">
                    <span style="font-size:12px; background:#f6ffed; color:#52c41a; border:1px solid #b7eb8f; padding:2px 6px; border-radius:4px;">校对通过</span>
                </div>
            </div>
        `;
    });

    const content = `
        <div class="batch-wizard" style="display:flex; height:100%; width:100%; background:#f5f7fa; overflow:hidden;">
            <div style="width:280px; display:flex; flex-direction:column; border-right:1px solid #dcdfe6; background:#fff; z-index:2;">
                <div style="padding:15px; border-bottom:1px solid #ebeef5; background:#fafafa;">
                    <h4 style="margin:0; color:#303133;">识别结果</h4>
                    <div style="font-size:12px; color:#909399; margin-top:5px;">共发现 ${groupKeys.length} 种表格结构</div>
                </div>
                <div style="flex:1; overflow-y:auto; padding:10px;" id="batch-group-list-container">
                    ${groupsHtml}
                </div>
            </div>

            <div style="flex:1; display:flex; flex-direction:column; overflow:hidden; background:#fff;">
                <div id="batch-mapping-header" style="padding:15px 20px; background:#fff; border-bottom:1px solid #ebeef5; min-height:60px; display:flex; justify-content:space-between; align-items:center;">
                    <!-- 动态内容 -->
                </div>

                <div id="unified-table-container" style="flex:1; padding:0; overflow:auto; background:#fff;">
                    <!-- 动态生成的一体化表格 -->
                </div>
                
                <div style="padding:12px 20px; background:#fff; border-top:1px solid #dcdfe6; display:flex; justify-content:flex-end; gap:12px; box-shadow: 0 -2px 8px rgba(0,0,0,0.06); z-index: 10;">
                    <span id="validation-msg" style="margin-right:auto; font-size:13px; display:flex; align-items:center;"></span>
                    <button class="btn-secondary" onclick="window.validateAllGroups()" style="border-color:#1890ff; color:#1890ff;">✨ 全部校对</button>
                    <button class="btn-secondary" onclick="window.validateCurrentGroup()">🔍 单组校对</button>
                    <div style="width:1px; background:#ddd; height:20px; align-self:center;"></div>
                    <button class="btn-secondary" onclick="window.closeBatchModal('${modalId}')">取消</button>
                    <button class="btn-primary" onclick="window.executeBatchImportAll('${dataType}', '${modalId}')">🚀 全部导入 (通过项)</button>
                </div>
            </div>
        </div>
    `;

    if (window.createTabInWorkbench) {
        window.createTabInWorkbench('batch-import-tab', `批量导入: ${getDataTypeName(dataType)}`, content);
        if (groupKeys.length > 0) {
            setTimeout(() => window.selectBatchGroup(groupKeys[0], dataType), 100);
        }
    }
}

window.removeBatchGroup = async function (key, event) {
    if (event) event.stopPropagation();

    const confirmed = await showConfirmModal('确定要移除这组表格吗？\n该组内的所有文件将不会被导入。');
    if (!confirmed) return;

    const card = document.getElementById(`group-card-${key}`);
    if (card) card.remove();
    delete currentImportGroups[key];

    if (key === activeGroupKey) {
        activeGroupKey = null;
        document.getElementById('batch-mapping-header').innerHTML = `<div style="color:#999; padding:20px;">请选择左侧分组进行配置</div>`;
        document.getElementById('unified-table-container').innerHTML = '';
        document.getElementById('validation-msg').innerHTML = '';
    }

    const remainingKeys = Object.keys(currentImportGroups);
    if (remainingKeys.length === 0) {
        alert('所有分组已被移除，导入流程结束。');
        window.closeBatchModal();
    } else if (activeGroupKey === null) {
        window.selectBatchGroup(remainingKeys[0], activeDataType);
    }
};

// [修复] 显式保存模板 (使用自定义弹窗)
window.saveAsNewTemplate = async function (groupKey) {
    const group = currentImportGroups[groupKey];

    window.saveGroupMapping(groupKey, true);

    if (!group.mapping || Object.keys(group.mapping).length === 0) {
        alert('请先配置字段映射关系！');
        return;
    }

    if (window.TemplateManager) {
        const defaultName = `${getDataTypeName(activeDataType)}模板_${new Date().toLocaleDateString().replace(/\//g, '')}`;

        // [修复] 使用 showInputModal 替代 prompt
        const tplName = await showInputModal('请输入模板名称:', defaultName);

        if (tplName) {
            const success = window.TemplateManager.saveUserTemplate(tplName, activeDataType, group.mapping);
            if (success) {
                group.templateName = tplName;
                if (groupKey === activeGroupKey) {
                    window.selectBatchGroup(groupKey, activeDataType);
                }
                alert('模板保存成功！下次导入相同结构的文件将自动匹配。');
            }
        }
    } else {
        alert('模板管理器未加载，无法保存。');
    }
};

// [修复] 暂存映射 (包含询问保存模板逻辑，使用自定义弹窗)
window.saveGroupMapping = function (groupKey, silent = false) {
    const group = currentImportGroups[groupKey];
    const mapping = {};
    let hasMapping = false;

    if (groupKey === activeGroupKey) {
        document.querySelectorAll('.batch-mapping-select').forEach(sel => {
            if (sel.value) {
                mapping[sel.dataset.header] = sel.value;
                hasMapping = true;
            }
        });
        if (hasMapping) group.mapping = mapping;
    } else {
        if (group.mapping && Object.keys(group.mapping).length > 0) {
            hasMapping = true;
        }
    }

    if (hasMapping) {
        const card = document.getElementById(`group-card-${groupKey}`);
        if (card) {
            card.style.borderLeftColor = '#52c41a';
            const statusSpan = document.getElementById(`status-badge-${groupKey}`);
            if (statusSpan) {
                statusSpan.innerText = '已配置';
                statusSpan.style.color = '#52c41a';
            }
        }

        // [修复] 使用 setTimeout 避免 UI 阻塞，并使用自定义确认框
        if (!silent && (!group.templateName || group.templateName === '自动识别') && window.TemplateManager) {
            setTimeout(async () => {
                const confirmed = await showConfirmModal('是否将当前的字段映射关系保存为新模板？\n保存后，下次导入相同格式文件可直接自动识别。');
                if (confirmed) {
                    window.saveAsNewTemplate(groupKey);
                }
            }, 200);
        }

        if (groupKey === activeGroupKey) {
            const btn = document.querySelector('button[onclick*="saveGroupMapping"]');
            if (btn) {
                const originalText = btn.innerHTML;
                btn.innerHTML = '<span>✓</span> 已暂存';
                btn.style.color = '#52c41a';
                btn.style.borderColor = '#b7eb8f';
                btn.style.background = '#f6ffed';
                setTimeout(() => {
                    btn.innerHTML = originalText;
                    btn.style.color = '';
                    btn.style.borderColor = '';
                    btn.style.background = '';
                }, 1500);
            }
        }
    } else {
        group.mapping = null;
    }
};

window.selectBatchGroup = function (groupKey, dataType) {
    activeGroupKey = groupKey;
    activeDataType = dataType;
    const group = currentImportGroups[groupKey];
    if (!group) return;

    document.querySelectorAll('.batch-group-card').forEach(el => {
        el.style.background = '#fff';
        el.style.borderColor = '#eee';
    });
    const activeCard = document.getElementById(`group-card-${groupKey}`);
    if (activeCard) {
        activeCard.style.background = '#e6f7ff';
        activeCard.style.borderColor = '#1890ff';
    }

    const headerContainer = document.getElementById('batch-mapping-header');
    const tplNameDisplay = group.templateName && group.templateName !== '自动识别'
        ? `<span style="color:#409eff; font-weight:bold;">${group.templateName}</span>`
        : `<span style="color:#909399;">未保存</span>`;

    headerContainer.innerHTML = `
        <div>
            <div style="font-size:16px; font-weight:600; color:#333;">配置映射规则</div>
            <div style="font-size:12px; color:#909399; margin-top:4px;">
                当前应用模版: ${tplNameDisplay}
            </div>
        </div>
        <div style="display:flex; gap:10px;">
             <button class="btn-secondary" style="padding:5px 12px; font-size:12px;" onclick="window.saveGroupMapping('${groupKey}')">暂存映射</button>
             <button class="btn-primary" style="padding:5px 12px; font-size:12px; background:#667eea; border-color:#667eea;" onclick="window.saveAsNewTemplate('${groupKey}')">💾 保存为新模板</button>
        </div>
    `;

    window.renderUnifiedTable(groupKey, dataType);

    const msgEl = document.getElementById('validation-msg');
    if (group.validationStatus === 'valid') {
        msgEl.innerHTML = `<span style="color:#52c41a; font-weight:bold;">✅ 校对通过</span>`;
    } else if (group.validationStatus === 'invalid') {
        msgEl.innerHTML = `<span style="color:#f56c6c; font-weight:bold;">❌ 校对失败：${group.validationError || '存在错误'}</span>`;
    } else {
        msgEl.innerHTML = `<span style="color:#909399;">⚠️ 请配置映射并进行数据校对</span>`;
    }
};

window.onMappingChange = function (groupKey) {
    const group = currentImportGroups[groupKey];
    const newMapping = {};
    document.querySelectorAll('.batch-mapping-select').forEach(sel => {
        if (sel.value) newMapping[sel.dataset.header] = sel.value;
    });
    group.mapping = newMapping;

    group.validationStatus = 'pending';
    document.getElementById(`validate-icon-${groupKey}`).style.display = 'none';
    document.getElementById('validation-msg').innerHTML = `<span style="color:#909399;">⚠️ 映射已修改，请重新校对</span>`;

    window.renderUnifiedTable(groupKey, activeDataType);
};

window.renderUnifiedTable = function (groupKey, dataType) {
    const group = currentImportGroups[groupKey];
    const container = document.getElementById('unified-table-container');

    if (!group.headers || group.headers.length === 0) return;

    const systemOptions = getSystemFieldOptions(dataType);
    const mappings = group.mapping || {};
    const previewData = group.previewData || [];

    let html = `<table style="border-collapse:separate; border-spacing:0; min-width:100%;">`;

    html += `<thead><tr>
        <th style="position:sticky; top:0; left:0; z-index:20; width:50px; background:#f0f2f5; border-right:1px solid #dcdfe6; border-bottom:1px solid #dcdfe6; height:40px;">#</th>`;

    group.headers.forEach(h => {
        html += `<th style="position:sticky; top:0; z-index:10; padding:10px; background:#f5f7fa; border-bottom:1px solid #ebeef5; border-right:1px solid #ebeef5; color:#303133; font-weight:600; min-width:150px; white-space:nowrap; box-shadow:0 1px 2px rgba(0,0,0,0.05);" title="${h}">${h}</th>`;
    });
    html += `</tr>`;

    html += `<tr>
        <th style="position:sticky; top:41px; left:0; z-index:20; background:#fff; border-right:1px solid #dcdfe6; border-bottom:2px solid #1890ff; height:40px;">🔗</th>`;

    group.headers.forEach(h => {
        const selectedVal = mappings[h] || '';
        const optionsHtml = systemOptions.map(opt =>
            `<option value="${opt.value}" ${opt.value === selectedVal ? 'selected' : ''}>${opt.label}</option>`
        ).join('');

        const isMapped = !!selectedVal;
        const borderBottom = isMapped ? '2px solid #52c41a' : '2px solid #e8e8e8';
        const bg = isMapped ? '#f6ffed' : '#fff';

        html += `<th style="position:sticky; top:41px; z-index:10; padding:8px; background:${bg}; border-bottom:${borderBottom}; border-right:1px solid #ebeef5;">
            <select class="batch-mapping-select" data-header="${h.replace(/"/g, '&quot;')}" onchange="window.onMappingChange('${groupKey}')" 
                    style="width:100%; padding:5px; border:1px solid #dcdfe6; border-radius:4px; font-size:13px; color:#333;">
                <option value="">(忽略)</option>
                ${optionsHtml}
                <option value="_custom_" ${selectedVal === '_custom_' ? 'selected' : ''}>★ 自定义</option>
            </select>
        </th>`;
    });
    html += `</tr></thead>`;

    html += `<tbody>`;

    if (previewData.length === 0) {
        html += `<tr><td colspan="${group.headers.length + 1}" style="padding:40px; text-align:center; color:#999;">暂无预览数据</td></tr>`;
    } else {
        previewData.forEach((row, idx) => {
            const cleanRow = {};
            Object.keys(mappings).forEach(origHeader => {
                const sysField = mappings[origHeader];
                let val = row[origHeader];

                if (['transaction_time', 'start_time', 'check_in_time'].includes(sysField)) {
                    if (window.Utils && window.Utils.formatDate) val = window.Utils.formatDate(val);
                }
                if (['transaction_amount', 'balance_after'].includes(sysField)) {
                    val = parseFloat(String(val).replace(/,/g, '').replace(/[^\d.-]/g, ''));
                    if (isNaN(val)) val = row[origHeader];
                }
                cleanRow[origHeader] = val;
            });

            html += `<tr>
                <td style="position:sticky; left:0; background:#f9f9f9; border-right:1px solid #eee; border-bottom:1px solid #eee; text-align:center; font-size:12px; color:#999;">${idx + 1}</td>`;

            group.headers.forEach(h => {
                const sysField = mappings[h];
                const isMapped = !!sysField;

                let val = isMapped ? cleanRow[h] : row[h];
                if (val === undefined || val === null) val = '';

                let cellStyle = 'padding:8px 10px; border-bottom:1px solid #eee; border-right:1px solid #eee; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:250px; font-size:13px;';

                if (isMapped) {
                    cellStyle += 'background-color:#f6ffed; color:#389e0d;';
                    if (['transaction_amount', 'balance_after'].includes(sysField) && isNaN(val)) {
                        cellStyle += 'color:red; font-weight:bold; background-color:#fff1f0;';
                    }
                } else {
                    cellStyle += 'color:#606266;';
                }

                html += `<td style="${cellStyle}" title="${val}">${val}</td>`;
            });
            html += `</tr>`;
        });
    }

    html += `</tbody></table>`;
    container.innerHTML = html;
};

function checkGroupValidity(group) {
    if (!group) return { valid: false, error: '分组不存在' };
    const defs = getFieldDefinitions(activeDataType);
    const mapping = group.mapping || {};
    const previewData = group.previewData || [];

    if (Object.keys(mapping).length < 1) return { valid: false, error: '未配置映射' };

    const mappedSysFields = Object.values(mapping);
    const missingRequired = defs.filter(d => d.required && !mappedSysFields.includes(d.key));
    if (missingRequired.length > 0) {
        return { valid: false, error: `缺失必填字段: ${missingRequired.map(d => d.label).join(', ')}` };
    }

    if (previewData.length > 0) {
        const amountCols = Object.keys(mapping).filter(k => {
            const def = defs.find(d => d.key === mapping[k]);
            return def && def.type === 'number';
        });

        for (let row of previewData) {
            for (let col of amountCols) {
                let val = row[col];
                if (val) {
                    val = parseFloat(String(val).replace(/,/g, ''));
                    if (isNaN(val)) {
                        return { valid: false, error: `字段 [${col}] 包含非数字内容` };
                    }
                }
            }
        }
    }
    return { valid: true };
}

window.validateCurrentGroup = function () {
    window.saveGroupMapping(activeGroupKey, true);

    const group = currentImportGroups[activeGroupKey];
    const result = checkGroupValidity(group);

    if (!result.valid) {
        group.validationStatus = 'invalid';
        group.validationError = result.error;
        document.getElementById(`validate-icon-${activeGroupKey}`).style.display = 'none';
        document.getElementById('validation-msg').innerHTML = `<span style="color:#f56c6c; font-weight:bold;">❌ ${result.error}</span>`;
        alert('校对失败：\n' + result.error);
    } else {
        group.validationStatus = 'valid';
        group.validationError = null;
        document.getElementById(`validate-icon-${activeGroupKey}`).style.display = 'block';
        document.getElementById('validation-msg').innerHTML = `<span style="color:#52c41a; font-weight:bold;">✅ 校对通过，数据格式正确</span>`;
    }
};

window.validateAllGroups = function () {
    if (activeGroupKey) window.saveGroupMapping(activeGroupKey, true);

    let passCount = 0;
    let failCount = 0;

    Object.keys(currentImportGroups).forEach(key => {
        const group = currentImportGroups[key];
        const result = checkGroupValidity(group);

        if (result.valid) {
            group.validationStatus = 'valid';
            group.validationError = null;
            passCount++;
            const icon = document.getElementById(`validate-icon-${key}`);
            if (icon) icon.style.display = 'block';
        } else {
            group.validationStatus = 'invalid';
            group.validationError = result.error;
            failCount++;
            const icon = document.getElementById(`validate-icon-${key}`);
            if (icon) icon.style.display = 'none';
        }
    });

    if (activeGroupKey) {
        const activeGroup = currentImportGroups[activeGroupKey];
        const msgEl = document.getElementById('validation-msg');
        if (activeGroup.validationStatus === 'valid') {
            msgEl.innerHTML = `<span style="color:#52c41a; font-weight:bold;">✅ 校对通过</span>`;
        } else {
            msgEl.innerHTML = `<span style="color:#f56c6c; font-weight:bold;">❌ 校对失败：${activeGroup.validationError || '存在错误'}</span>`;
        }
    }

    alert(`批量校对完成！\n\n✅ 通过：${passCount} 组\n❌ 失败：${failCount} 组\n\n提示：点击“全部导入”时，将只导入通过校对的分组。`);
};

window.executeBatchImportAll = async function (dataType, modalId) {
    const groupKeys = Object.keys(currentImportGroups);
    const validGroups = groupKeys.filter(k => currentImportGroups[k].validationStatus === 'valid');

    if (validGroups.length === 0) {
        alert('没有通过校对的分组！\n请先点击“全部校对”或单个“数据校对”按钮。');
        return;
    }

    const totalValidFiles = validGroups.reduce((sum, k) => sum + currentImportGroups[k].files.length, 0);

    // [修复] 使用自定义确认框
    const confirmed = await showConfirmModal(`即将导入 ${validGroups.length} 个结构组，共 ${totalValidFiles} 个工作表。\n只有【校对通过】的组才会被导入。\n是否继续？`);
    if (!confirmed) return;

    if (window.closeTab) window.closeTab('batch-import-tab');

    const progressDiv = document.createElement('div');
    progressDiv.style.cssText = 'position:fixed; bottom:20px; right:20px; width:350px; background:white; box-shadow:0 4px 20px rgba(0,0,0,0.2); border-radius:8px; padding:20px; z-index:10000; border:1px solid #ebeef5;';
    progressDiv.innerHTML = `<div id="batch-progress-text">正在初始化...</div><div style="height:8px;background:#eee;margin-top:10px;"><div id="batch-progress-bar" style="height:100%;width:0;background:#1890ff;"></div></div>`;
    document.body.appendChild(progressDiv);

    let processed = 0;
    let successSheetCount = 0;
    let totalRecords = 0;
    let totalImported = 0;
    let totalDuplicates = 0;
    let failedInfo = [];

    for (const key of validGroups) {
        const group = currentImportGroups[key];
        for (const fileItem of group.files) {
            document.getElementById('batch-progress-text').innerText = `正在导入: ${fileItem.fileName} - ${fileItem.sheet}`;
            try {
                const parseResult = await window.electronAPI.file.parse(fileItem.path, dataType, { sheetName: fileItem.sheet });
                if (parseResult.success) {
                    const cleanedData = parseResult.fullData.map(row => normalizeRowData(row, dataType, group.mapping));

                    if (cleanedData.length === 0) {
                        failedInfo.push(`${fileItem.fileName} (${fileItem.sheet}): 数据为空`);
                    } else {
                        const res = await window.electronAPI.data.import({
                            dataType,
                            caseId: sessionStorage.getItem('currentCaseId'),
                            data: cleanedData,
                            sourceFile: `${fileItem.fileName} [${fileItem.sheet}]`,
                            skipFileCheck: true
                        });

                        if (res.success) {
                            successSheetCount++;
                            totalRecords += (res.totalCount || 0);
                            totalImported += (res.importedCount || 0);
                            totalDuplicates += (res.duplicateCount || 0);
                        } else {
                            failedInfo.push(`${fileItem.fileName} (${fileItem.sheet}): ${res.message}`);
                        }
                    }
                } else {
                    failedInfo.push(`${fileItem.fileName} (${fileItem.sheet}): 解析失败`);
                }
            } catch (e) {
                console.error(e);
                failedInfo.push(`${fileItem.fileName}: ${e.message}`);
            }
            processed++;
            document.getElementById('batch-progress-bar').style.width = (processed / totalValidFiles * 100) + '%';
            await new Promise(r => setTimeout(r, 50));
        }
    }

    let msg = `共处理 <b>${processed}</b> 个工作表<br>
               数据总量: ${totalRecords} 条<br>
               <span style="color:#52c41a">成功入库: <b>${totalImported}</b> 条</span><br>
               <span style="color:#faad14">重复跳过: <b>${totalDuplicates}</b> 条</span>`;

    if (failedInfo.length > 0) {
        msg += `<br><br><span style="color:red">失败 ${failedInfo.length} 个:</span><br>${failedInfo.slice(0, 3).join('<br>')}${failedInfo.length > 3 ? '...' : ''}`;
    }

    progressDiv.innerHTML = `
        <div style="margin-bottom:10px; font-weight:bold; color:#303133; font-size:16px;">✅ 批量导入完成</div>
        <div style="font-size:13px; color:#606266; margin-bottom:20px; line-height:1.6;">
            ${msg}
        </div>
        <button onclick="this.parentElement.remove()" style="width:100%; padding:8px; border:1px solid #dcdfe6; background:#f5f7fa; border-radius:4px; cursor:pointer; color:#606266; font-weight:500;">关闭</button>
    `;
};

window.closeBatchModal = function (modalId) {
    if (window.closeTab) window.closeTab('batch-import-tab');
};

// 数据清洗逻辑
function normalizeRowData(row, dataType, mappings) {
    const systemRow = {};
    const extraData = {};

    const defs = getFieldDefinitions(dataType);
    const dateFields = defs.filter(d => d.type === 'date').map(d => d.key);
    const numberFields = defs.filter(d => d.type === 'number').map(d => d.key);

    for (const [origField, sysField] of Object.entries(mappings)) {
        let val = row[origField];
        if (val === undefined) {
            const k = Object.keys(row).find(key => key.trim().toLowerCase() === origField.trim().toLowerCase());
            if (k) val = row[k];
        }

        if (val && typeof val === 'object' && !(val instanceof Date)) {
            val = val.result || val.text || val.value || '';
        }

        if (sysField === '_custom_') {
            extraData[origField] = val;
        } else if (sysField) {
            if (dateFields.includes(sysField)) {
                if (window.Utils && window.Utils.formatDate) {
                    val = window.Utils.formatDate(val);
                }
            }
            if (numberFields.includes(sysField) && val) {
                val = parseFloat(String(val).replace(/,/g, '').replace(/[^\d.-]/g, ''));
            }
            systemRow[sysField] = val;
        }
    }

    if (Object.keys(extraData).length > 0) {
        systemRow.extra_data = JSON.stringify(extraData);
    }

    if (Object.keys(mappings || {}).length === 0) {
        const knownFields = [
            'account_number', 'counterparty_account', 'transaction_amount', 'transaction_type',
            'balance_after', 'remarks', 'customer_name', 'id_number', 'phone_number',
            'user_number', 'opp_user_number', 'duration', 'call_type',
            'name', 'address', 'unit'
        ];
        Object.keys(row).forEach(key => {
            if (knownFields.includes(key)) systemRow[key] = row[key];
        });
    }

    return systemRow;
}

// 简易自动匹配逻辑
function trySimpleAutoMap(dataType, headers) {
    const mapping = {};
    const keywords = {
        'id_number': ['身份证', '证件号'],
        'phone_number': ['手机', '电话'],
        'name': ['名称', '姓名'],
        'transaction_time': ['交易时间', '日期', '发生时间'],
        'transaction_amount': ['交易金额', '发生额', '金额'],
        'counterparty_name': ['对方户名', '对方姓名'],
        'counterparty_account': ['对方账号', '对方卡号'],
        'account_number': ['本方账号', '卡号'],
        'user_number': ['本机号码', '主叫号码'],
        'opp_user_number': ['对方号码', '被叫号码'],
        'duration': ['时长', '通话时长'],
        'start_time': ['开始时间', '通话时间'],
        'hotel_name': ['旅店名称', '酒店'],
        'check_in_time': ['入住时间'],
        'train_number': ['车次', '车号'],
        'flight_number': ['航班号'],
        'departure_station': ['出发地', '发站', '起飞'],
        'arrival_station': ['目的地', '到站', '降落']
    };

    headers.forEach(h => {
        for (const [sysKey, words] of Object.entries(keywords)) {
            if (words.some(w => h.includes(w))) {
                mapping[h] = sysKey;
                break;
            }
        }
    });
    return mapping;
}

// [新增] 自定义输入弹窗
function showInputModal(title, defaultValue = '') {
    return new Promise((resolve) => {
        const modalId = `input-modal-${Date.now()}`;
        const html = `
            <div id="${modalId}" style="position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:10001; display:flex; justify-content:center; align-items:center;">
                <div style="background:white; padding:20px; border-radius:6px; width:300px; box-shadow:0 4px 12px rgba(0,0,0,0.15);">
                    <h3 style="margin:0 0 15px 0; font-size:16px; color:#333;">${title}</h3>
                    <input type="text" id="${modalId}-input" value="${defaultValue}" style="width:100%; padding:8px; border:1px solid #dcdfe6; border-radius:4px; margin-bottom:15px; box-sizing:border-box;">
                    <div style="text-align:right; display:flex; justify-content:flex-end; gap:10px;">
                        <button id="${modalId}-cancel" class="btn-secondary" style="padding:6px 15px; font-size:13px;">取消</button>
                        <button id="${modalId}-confirm" class="btn-primary" style="padding:6px 15px; font-size:13px;">确定</button>
                    </div>
                </div>
            </div>
        `;
        document.body.insertAdjacentHTML('beforeend', html);

        const modal = document.getElementById(modalId);
        const input = document.getElementById(`${modalId}-input`);
        const btnConfirm = document.getElementById(`${modalId}-confirm`);
        const btnCancel = document.getElementById(`${modalId}-cancel`);

        input.focus();
        input.select();

        const cleanup = () => modal.remove();

        btnConfirm.onclick = () => {
            const val = input.value.trim();
            if (val) {
                resolve(val);
                cleanup();
            } else {
                alert('名称不能为空');
            }
        };

        btnCancel.onclick = () => {
            resolve(null);
            cleanup();
        };

        input.onkeydown = (e) => {
            if (e.key === 'Enter') btnConfirm.click();
            if (e.key === 'Escape') btnCancel.click();
        };
    });
}

// [新增] 自定义确认弹窗
function showConfirmModal(message) {
    return new Promise((resolve) => {
        const modalId = `confirm-modal-${Date.now()}`;
        const html = `
            <div id="${modalId}" style="position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:10001; display:flex; justify-content:center; align-items:center;">
                <div style="background:white; padding:20px; border-radius:6px; width:350px; box-shadow:0 4px 12px rgba(0,0,0,0.15);">
                    <div style="margin-bottom:20px; color:#333; font-size:14px; line-height:1.5;">${message.replace(/\n/g, '<br>')}</div>
                    <div style="text-align:right; display:flex; justify-content:flex-end; gap:10px;">
                        <button id="${modalId}-cancel" class="btn-secondary" style="padding:6px 15px; font-size:13px;">取消</button>
                        <button id="${modalId}-confirm" class="btn-primary" style="padding:6px 15px; font-size:13px;">确定</button>
                    </div>
                </div>
            </div>
        `;
        document.body.insertAdjacentHTML('beforeend', html);

        const modal = document.getElementById(modalId);
        const btnConfirm = document.getElementById(`${modalId}-confirm`);
        const btnCancel = document.getElementById(`${modalId}-cancel`);

        const cleanup = () => modal.remove();

        btnConfirm.onclick = () => {
            resolve(true);
            cleanup();
        };

        btnCancel.onclick = () => {
            resolve(false);
            cleanup();
        };
    });
}

// 暴露给全局
window.DataModule = {
    getDataTypeName,
    getSystemFieldOptions,
    initializeDataModule: () => console.log('Data Module Ready')
};